﻿//#define FULL_TRACE

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;

using alib;
using alib.Bits;
using alib.Debugging;
using alib.Enumerable;
using alib.Reflection;

namespace agree.schema
{
	using xaml;

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// schema_type
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public abstract class schema_type : Type, _Type
	{
		protected static readonly Type UnsetValue;

		static schema_type()
		{
			UnsetValue = new TypeDelegator(typeof(Object));
		}

		protected schema_type(Schema sch, Type t, int ix)
		{
			Debug.Assert(t.IsRuntimeType() && !t.IsEnum && !t.IsGenericParameter);

			this.id = -1;
			this.sch = sch;
			this.t = t;
			this.hash_ix = ix;
			this.type_code = Type.GetTypeCode(t);
			this.metadata_token = t.MetadataToken;
			this.rth = t.TypeHandle;
			this._fullname = t.FullName;
			this.guid = Guid.NewGuid();
			this.f_valuetype = t.IsValueType;
			this.attr = t.Attributes;
			this._namespace = t.Namespace;

			this.t_base = UnsetValue;
			this.t_refl = UnsetValue;
		}

		public readonly Schema sch;
		protected readonly Type t;
		protected readonly int hash_ix;
		readonly TypeCode type_code;
		readonly int metadata_token;
		readonly RuntimeTypeHandle rth;
		readonly Guid guid;
		readonly bool f_valuetype;
		readonly TypeAttributes attr;
		readonly String _namespace;
		readonly String _fullname;

		public int id;

		public abstract schema_type_known KnownType { get; }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///

		xaml_type xt;
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public xaml_type XamlType
		{
			get
			{
				return xt ?? (xt = t.IsInterface || t.IsAbstract ? (xaml_type)
									new xaml_abstract_type(this) :
									new xaml_class_type(this));
			}
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///

		public sealed override MemberTypes MemberType { get { return MemberTypes.TypeInfo; } }

		public sealed override RuntimeTypeHandle TypeHandle { get { return rth; } }

		public sealed override Type UnderlyingSystemType { get { return this.t; } }

		public sealed override int MetadataToken { get { return metadata_token; } }

		public sealed override Guid GUID { get { return guid; } }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///

		public sealed override Module Module { get { return t.Module; } }

		public sealed override Assembly Assembly { get { return t.Assembly; } }

		public sealed override String AssemblyQualifiedName { get { return t.AssemblyQualifiedName; } }

		public sealed override String Namespace { get { return _namespace; } }

		public sealed override String FullName { get { return _fullname; } }

		protected String _name;
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public sealed override String Name
		{
			//get { return _name ?? (_name = alib.Reflection.reflection._Name(t)); }
			get { return _name ?? (_name = t.Name); }
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///

		Type t_base;
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public override Type BaseType
		{
			get
			{
				Type _tmp;
				return (_tmp = t_base) != UnsetValue ? _tmp : t_base = sch.promote_type(t.BaseType);
			}
		}

		Type t_refl;
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public sealed override Type ReflectedType
		{
			get
			{
				Type _tmp;
				return (_tmp = t_refl) != UnsetValue ? _tmp : t_refl = sch.promote_type(t.ReflectedType);
			}
		}

		public sealed override Type DeclaringType { get { return null; } }

		public sealed override MethodBase DeclaringMethod { get { return null; } }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///

		public override Type MakePointerType() { return t.MakePointerType(); }

		public override Type MakeByRefType() { return t.MakeByRefType(); }

		public override Type MakeArrayType() { return t.MakeArrayType(); }

		public override Type MakeArrayType(int rank) { return t.MakeArrayType(rank); }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// inheritance and interfaces

		Type[] _interfaces;
		public override Type[] GetInterfaces()
		{
			if (_interfaces == null)
				_interfaces = sch.promote_types(t.GetInterfaces());
			return _interfaces;
		}

		public override Type GetInterface(String s, bool f_ignore_case)
		{
			if (s == null)
				return null;

			int ix;
			String ns = "";

			if ((ix = s.LastIndexOf('.')) != -1)
			{
				ns = s.Substring(0, ix);
				s = s.Substring(ix + 1);
			}

			var bf = BindingFlags.NonPublic | BindingFlags.Public;
			if (f_ignore_case)
				bf |= BindingFlags.IgnoreCase;

			Type t_ret = null, t;

			var arr = GetInterfaces();
			for (int i = 0; i < arr.Length; i++)
				if ((t = arr[i].FilterApplyType(bf, s, false, ns)) != null)
					if (t_ret != null)
						throw new AmbiguousMatchException();
					else
						t_ret = t;
			return t_ret;
		}

		public unsafe override Type[] FindInterfaces(TypeFilter filter, Object o_fltr_crtr)
		{
			var src = this.GetInterfaces();
			if (src.Length == 0)
				return Type.EmptyTypes;

			ulong* pul = stackalloc ulong[Bitz.ComputeSize(src.Length)];
			int i, c;
			for (i = 0, c = 0; i < src.Length; i++)
				if (filter(src[i], o_fltr_crtr))
				{
					Bitz.Set(pul, i);
					c++;
				}

			if (c == src.Length)
				return src;

			var ret = new Type[c];
			for (i = 0, c = 0; c < ret.Length; i++)
				if (Bitz.Test(pul, i))
					ret[c++] = src[i];
			return ret;
		}

		public override InterfaceMapping GetInterfaceMap(Type T_intr_typ)
		{
			return t.GetInterfaceMap(T_intr_typ);
		}

		public override bool IsSubclassOf(Type c)
		{
			return t.IsSubclassOf(c);
		}

		public sealed override bool IsInstanceOfType(Object o)
		{
			return t.IsAssignableFrom(o.GetType().UnderlyingSystemType);
		}

		public override bool IsEquivalentTo(Type other)
		{
			return (Object)t == (Object)other.UnderlyingSystemType;
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// collection

		protected override bool HasElementTypeImpl() { return t.HasElementType; }

		public override Type GetElementType() { return t.GetElementType(); }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// Impl

		protected override TypeCode GetTypeCodeImpl() { return type_code; }

		protected override bool IsValueTypeImpl() { return f_valuetype; }

		protected override TypeAttributes GetAttributeFlagsImpl() { return attr; }

		protected override bool IsByRefImpl() { return false; }

		protected override bool IsPointerImpl() { return false; }

		protected override bool IsPrimitiveImpl() { return false; }

		protected override bool IsCOMObjectImpl() { return false; }

		protected override bool IsContextfulImpl() { return false; }

		protected override bool IsMarshalByRefImpl() { return false; }

		protected override bool IsArrayImpl() { return false; }

		protected override ConstructorInfo GetConstructorImpl(BindingFlags bf, Binder binder, CallingConventions cc, Type[] types, ParameterModifier[] modifiers)
		{
			//dbg.write(GetType().Name + ".GetConstructorImpl... ");
#if proxy_ctor
			var x = new _ci_proxy(this);
#else
			var x = t.GetConstructor(bf, binder, cc, types, modifiers);
#endif
			//dbg.objinf(x);
			return x;
		}

		protected override MethodInfo GetMethodImpl(String name, BindingFlags bf, Binder binder, CallingConventions cc, Type[] types, ParameterModifier[] modifiers)
		{
			dbg.write(GetType().Name + ".GetMethodImpl... ");
			MethodInfo x = types == null ? t.GetMethod(name, bf) : t.GetMethod(name, bf, binder, cc, types, modifiers);
			dbg.objinf(x);
			return x;
		}

		protected override PropertyInfo GetPropertyImpl(String name, BindingFlags bf, Binder binder, Type T_return, Type[] types, ParameterModifier[] modifiers)
		{
			dbg.write(GetType().Name + ".GetPropertyImpl... ");
			PropertyInfo x;
			if (types != null)
				x = t.GetProperty(name, bf, binder, T_return, types, modifiers);
			else if (T_return == null)
				x = t.GetProperty(name, bf);
			else
				x = t.GetProperty(name, T_return);

			if (x == null)
			{
				var ap = sch.GetAttachedProp(name);
				if (ap != null)
				{
					x = ap;
				}
			}
			dbg.objinf(x);
			return x;
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// members

		public override MemberInfo[] GetMember(String name, BindingFlags bf) { return GetMember(name, MemberTypes.All, bf); }

		public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bf)
		{
			dbg.write(GetType().Name + ".GetMember3(“" + name + "”)... ");

			var rg = t.GetMember(name, type, bf);

			dbg.objinf(rg);

			return rg;
		}

		public override MemberInfo[] GetMembers(BindingFlags bf)
		{
			dbg.write(GetType().Name + ".GetMembers... ");
			try
			{
				var x = t.GetMembers(bf);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		public override MemberInfo[] FindMembers(MemberTypes mt, BindingFlags bf, MemberFilter filter, Object o_fltr_crtr)
		{
			dbg.write(GetType().Name + ".FindMembers... ");
			try
			{
				var x = t.FindMembers(mt, bf, filter, o_fltr_crtr);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		public override Object InvokeMember(String name, BindingFlags bf, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] rgs)
		{
			dbg.write(GetType().Name + ".InvokeMember... ");
			try
			{
				var x = t.InvokeMember(name, bf, binder, target, args, modifiers, culture, rgs);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		public override MemberInfo[] GetDefaultMembers()
		{
			dbg.write(GetType().Name + ".GetDefaultMembers... ");
			try
			{
				var x = t.GetDefaultMembers();
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// methods

		public override MethodInfo[] GetMethods(BindingFlags bf)
		{
			dbg.write(GetType().Name + ".GetMethods... ");
			try
			{
				var x = t.GetMethods(bf);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// constructors

		public override ConstructorInfo[] GetConstructors(BindingFlags bf)
		{
			dbg.write(GetType().Name + ".GetConstructors... ");
			try
			{
#if proxy_ctor
				var x = new ConstructorInfo[] { new _ci_proxy(this) };
#else
				var x = t.GetConstructors(bf);
#endif
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// properties

		public override PropertyInfo[] GetProperties(BindingFlags bf)
		{
			dbg.write(GetType().Name + ".GetProperties... ");
			try
			{
				var x = t.GetProperties(bf);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// fields

		public override FieldInfo GetField(String name, BindingFlags bf)
		{
			dbg.write(GetType().Name + ".GetField... ");
			try
			{
				var x = t.GetField(name, bf);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}
		public override FieldInfo[] GetFields(BindingFlags bf)
		{
			dbg.write(GetType().Name + ".GetFields... ");
			try
			{
				var x = t.GetFields(bf);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// attributes

		public sealed override IEnumerable<CustomAttributeData> CustomAttributes
		{
			get
			{
				dbg.write(GetType().Name + ".CustomAttributes... ");
				try
				{
					var x = t.CustomAttributes;
					dbg.objinf(x);
					return x;
				}
				catch (Exception ex) { dbg.ex_info(ex); throw; }
			}
		}

		public override Object[] GetCustomAttributes(bool inherit)
		{
			dbg.write(GetType().Name + ".GetCustomAttributes... ");
			try
			{
				var x = t.GetCustomAttributes(inherit);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		public override Object[] GetCustomAttributes(Type T_attr_typ, bool inherit)
		{
			dbg.write(GetType().Name + ".GetCustomAttributes... ");
			try
			{
				var x = t.GetCustomAttributes(T_attr_typ, inherit);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}
		public override bool IsDefined(Type T_attr_typ, bool inherit)
		{
			dbg.write(GetType().Name + ".IsDefined... ");
			try
			{
				var x = t.IsDefined(T_attr_typ, inherit);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}
		public override IList<CustomAttributeData> GetCustomAttributesData()
		{
			dbg.write(GetType().Name + ".GetCustomAttributesData... ");
			try
			{
				var x = t.GetCustomAttributesData();
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// nested types

		public override Type[] GetNestedTypes(BindingFlags bf) { return t.GetNestedTypes(bf); }

		public override Type GetNestedType(String name, BindingFlags bf) { return t.GetNestedType(name, bf); }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// events

		public override EventInfo GetEvent(String name, BindingFlags bf) { return t.GetEvent(name, bf); }

		public override EventInfo[] GetEvents() { return t.GetEvents(); }

		public override EventInfo[] GetEvents(BindingFlags bf) { return t.GetEvents(bf); }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///

		public override int GetArrayRank() { throw not.valid; }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		///

		public sealed override bool IsEnum { get { return false; } }

		public sealed override bool IsGenericParameter { get { return false; } }

		public sealed override bool IsSecurityCritical { get { return true; } }

		public sealed override bool IsSecuritySafeCritical { get { return false; } }

		public sealed override bool IsSecurityTransparent { get { return false; } }

		public sealed override bool IsSerializable { get { return false; } }

		public sealed override String[] GetEnumNames() { throw not.valid; }

		public sealed override Array GetEnumValues() { throw not.valid; }

		public sealed override Type GetEnumUnderlyingType() { throw not.valid; }

		public sealed override bool IsEnumDefined(Object value) { throw not.valid; }

		public sealed override String GetEnumName(Object value) { throw not.valid; }

		public sealed override StructLayoutAttribute StructLayoutAttribute { get { return t.StructLayoutAttribute; } }

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// 
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

		MethodInfo mi_multi;
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public MethodInfo MultiAddMethod
		{
			get { return mi_multi ?? (this.mi_multi = t.GetMethod("MultiAdd")); }
		}
	};

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// 
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public abstract class schema_type_known : schema_type, IComparable<schema_type_known>
	{
		public schema_type_known(Schema sch, Type t, int c_types, int ix)
			: base(sch, t, ix)
		{
			Debug.Assert(!t.IsConstructedGenericType);
			this.ext_idx = new alib.Hashing.StringIndex(4);
		}

		MethodInfo[] prop_callbacks;
		public void AddPropchangeCallback(MethodInfo[] rgmi)
		{
			if (prop_callbacks == null)
				prop_callbacks = rgmi;
			else
				alib.Array.arr.Append(ref prop_callbacks, rgmi[0]);
		}
		public void do_prop_cbs(Object obj, Object value)
		{
			MethodInfo[] _tmp;
			if ((_tmp = prop_callbacks) != null)
				for (int i = 0; i < _tmp.Length; i++)
					_tmp[i].Invoke(null, 0, null, new Object[] { obj, this, value }, null);
		}

		MethodInfo[] newobj_callbacks;
		public void AddNewObjCallback(MethodInfo[] rgmi)
		{
			if (newobj_callbacks == null)
				newobj_callbacks = rgmi;
			else
				alib.Array.arr.Append(ref newobj_callbacks, rgmi[0]);
		}
		public void do_newobj(schema_type t, Object obj)
		{
			MethodInfo[] _tmp;
			if ((_tmp = newobj_callbacks) != null)
				for (int i = 0; i < _tmp.Length; i++)
					_tmp[i].Invoke(null, 0, null, new Object[] { t, obj }, null);
		}

		alib.Hashing.StringIndex ext_idx;
		MethodInfo[] _extensions;
		public void AddExtension(MethodInfo mi)
		{
			lock (ext_idx)
			{
				int ix = ext_idx.Add(mi.Name);
				if (ix != (_extensions == null ? 0 : _extensions.Length))
					throw new Exception();
				_extensions = alib.Array.arr.Append(_extensions, mi);
			}
		}

		public sealed override bool IsConstructedGenericType { get { return false; } }

		public int CompareTo(schema_type_known other)
		{
			int d;
			if ((d = Compare(this as schema_type_norm, other as schema_type_norm)) != 0)
				return d;

			bool b;
			if ((b = this is schema_type_generic_def) != (other is schema_type_generic_def))
				return b ? -1 : 1;

			return Compare(this.t, other.t);
		}
		static int Compare(schema_type_norm t1, schema_type_norm t2)
		{
			bool b;
			return (b = t1 == default(Object)) != (t2 == default(Object)) ? b ? -1 : 1 : b ? 0 : t1.level - t2.level;
		}
		static int Compare(Type t1, Type t2)
		{
			bool b;
			if ((b = t1.IsAbstract) != t2.IsAbstract)
				return b ? -1 : 1;
			return String.CompareOrdinal(t1.Name, t2.Name);
		}

		public sealed override schema_type_known KnownType { get { return this; } }
	};

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// 
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public sealed class schema_type_norm : schema_type_known
	{
		public schema_type_norm(Schema sch, Type t, int c_types, int ix)
			: base(sch, t, c_types, ix)
		{
			Debug.Assert(!t.IsGenericType && !t.IsGenericTypeDefinition && !t.ContainsGenericParameters);

			this.level = -1;
			(this.bitz = Bitz.Init(c_types)).Set(ix);
		}

		readonly ulong[] bitz;
		public int level;	/// <summary> number of bits set in 'bitz' - 1. </summary>

		public void init_phase_two()
		{
			this.level = 0;

			Type tb = this.t;
			int ixT_base;
			while ((tb = tb.BaseType) != null && (ixT_base = sch.sys_type_index[tb]) != -1)
			{
				bitz.Set(ixT_base);
				level++;
			}

			var rgint = (Type[])t.GetInterfaces();
			for (int i = 0; i < rgint.Length; i++)
			{
				if ((ixT_base = sch.sys_type_index[rgint[i]]) != -1)
				{
					bitz.Set(ixT_base);
					level++;
				}
			}
		}

		public override bool IsAssignableFrom(Type other)
		{
			if ((Object)this == (Object)other)
				return true;

			schema_type_norm t_other;

			if (level == -1 || (t_other = sch.promote_to<schema_type_norm>(other)) == null)
				return t.IsAssignableFrom(other);

			Debug.Assert(t_other.level != -1);

			return level == t_other.level ? (Object)this == (Object)t_other : t_other.bitz.Test(hash_ix);
		}

		public override bool IsGenericType { get { return false; } }

		public override bool IsGenericTypeDefinition { get { return false; } }

		public override Type MakeGenericType(Type[] rgt) { throw not.valid; }

		public override Type GetGenericTypeDefinition() { throw not.valid; }

		public override Type[] GetGenericArguments() { throw not.valid; }

		public override bool ContainsGenericParameters { get { return false; } }

		public override GenericParameterAttributes GenericParameterAttributes { get { throw not.valid; } }

		public override Type[] GetGenericParameterConstraints() { throw not.valid; }

		public override int GenericParameterPosition { get { throw not.valid; } }

		public override String ToString()
		{
			return String.Format("{0,2} {1,2} {2}", id, level, _name);
		}
	};

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// 
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public sealed class schema_type_generic_def : schema_type_known
	{
		public schema_type_generic_def(Schema sch, Type t, int c_types, int ix)
			: base(sch, t, c_types, ix)
		{
			Debug.Assert(t.IsGenericType && t.IsGenericTypeDefinition && t.ContainsGenericParameters);
			this._gdef = UnsetValue;
		}

		public override bool IsGenericType { get { return true; } }

		public override bool IsGenericTypeDefinition { get { return true; } }

		public override bool ContainsGenericParameters { get { return true; } }

		public override bool IsAssignableFrom(Type c) { throw not.valid; }

		public override Type[] GetGenericArguments()
		{
			var arr = t.GetGenericArguments();
			for (int i = 0; i < arr.Length; i++)
				sch.promote_type(ref arr[i]);
			return arr;
		}

		Type _gdef;
		public override Type GetGenericTypeDefinition()
		{
			if (_gdef == UnsetValue)
				_gdef = sch.promote_type(t.GetGenericTypeDefinition());
			return _gdef;
		}

		public override GenericParameterAttributes GenericParameterAttributes
		{
			get
			{
				dbg.write(GetType().Name + ".GenericParameterAttributes... ");
				try
				{
					var x = t.GenericParameterAttributes;
					dbg.objinf(x);
					return x;
				}
				catch (Exception ex) { dbg.ex_info(ex); throw; }
			}
		}

		public override Type[] GetGenericParameterConstraints()
		{
			dbg.write(GetType().Name + ".GetGenericParameterConstraints... ");
			try
			{
				var x = t.GetGenericParameterConstraints();
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}


		public override int GenericParameterPosition
		{
			get
			{
				dbg.write(GetType().Name + ".GenericParameterPosition... ");
				try
				{
					var x = t.GenericParameterPosition;
					dbg.objinf(x);
					return x;
				}
				catch (Exception ex) { dbg.ex_info(ex); throw; }
			}
		}

		public override Type MakeGenericType(Type[] rgt)
		{
			dbg.write(GetType().Name + ".MakeGenericType... ");
			try
			{
				var x = t.MakeGenericType(rgt);
				dbg.objinf(x);
				return x;
			}
			catch (Exception ex) { dbg.ex_info(ex); throw; }
		}
	};

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// 
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public sealed class schema_type_generic : schema_type
	{
		public schema_type_generic(Schema sch, Type t, int ix)
			: base(sch, t, ix)
		{
			Debug.Assert(t.IsGenericType && !t.IsGenericTypeDefinition && t.IsConstructedGenericType && !t.ContainsGenericParameters);
			this.gdef = (schema_type_generic_def)sch.promote_type(t.GetGenericTypeDefinition());
		}

		public override bool IsAssignableFrom(Type c)
		{
			var x = t.IsAssignableFrom(c);
			return x;
		}

		public override bool IsGenericType { get { return true; } }

		public override bool IsConstructedGenericType { get { return true; } }

		Type[] _gargs;
		public override Type[] GetGenericArguments()
		{
			if (_gargs == null)
				_gargs = sch.promote_types(t.GetGenericArguments());
			return _gargs;
		}

		public sealed override schema_type_known KnownType { get { return this.gdef; } }

		schema_type_generic_def gdef;
		public override Type GetGenericTypeDefinition() { return this.gdef; }

		public override bool IsGenericTypeDefinition { get { return false; } }

		public override bool ContainsGenericParameters { get { return false; } }

		public override Type MakeGenericType(Type[] rgt) { throw not.valid; }

		public override Type[] GetGenericParameterConstraints() { throw not.valid; }

		public override int GenericParameterPosition { get { throw not.valid; } }

		public override GenericParameterAttributes GenericParameterAttributes { get { throw not.valid; } }
	};
}
